import XCTest
@testable import URRegistry

final class URRegistryTests: XCTestCase {
    func testGetSourceHDKeyWithStandardNote() {
        let ur = "UR:CRYPTO-HDKEY/PTAOWKAXHDCLAXDLGHLBTLDARPTPFNSASSGWMUNSSEFWHEOYWLLGMSTDJEAEYTVOTIGAGMMUFNGYDEAAHDCXRHDNCHQDMUHSDLSPWLFEVWSKETMWESSGBNBKDESRATJZAMBDBZSRYTYNGMFTNTCFAHTAADEHOEADCSFNAOAEAMTAADDYOTADLNCSDWYKCSFNYKAEYKAOCYGMAEJTNBAXAXATTAADDYOEADLRAEWKLAWKAXAEAYCYWDBZJZTYASISGRIHKKJKJYJLJTIHBKJOHSIAIAJLKPJTJYDMJKJYHSJTIEHSJPIEEOSPLADY"
        let expectedResult = CryptoHDKey(
            key: "032f547fd525b6d83cc2c44f939cc1425fa1e98d97d26b00f9e2d04952933c5128",
            chainCode: "b92b17b393612fc8e945e5c5389439ca0c0a28c3076c060b15c3f9f6523a9d19",
            sourceFingerprint: 1375760032,
            note: .standard
        )
        
        let sut = URRegistry.shared
        
        let result = sut.getSourceHDKey(from: ur)
        
        XCTAssertEqual(result, expectedResult)
    }
    
    func testGetSourceHDKeyWithLedgerLegacyNote() {
        let ur = "UR:CRYPTO-HDKEY/PTAOWKAXHDCLAXDLGHLBTLDARPTPFNSASSGWMUNSSEFWHEOYWLLGMSTDJEAEYTVOTIGAGMMUFNGYDEAAHDCXRHDNCHQDMUHSDLSPWLFEVWSKETMWESSGBNBKDESRATJZAMBDBZSRYTYNGMFTNTCFAHTAADEHOEADCSFNAOAEAMTAADDYOTADLNCSDWYKCSFNYKAEYKAOCYGMAEJTNBAXAXATTAADDYOEADLFLAWKAXAEAYCYWDBZJZTYASISGRIHKKJKJYJLJTIHBKKPHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZIHIOHSIAKKSWTBSPAS"
        let expectedResult = CryptoHDKey(
            key: "032f547fd525b6d83cc2c44f939cc1425fa1e98d97d26b00f9e2d04952933c5128",
            chainCode: "b92b17b393612fc8e945e5c5389439ca0c0a28c3076c060b15c3f9f6523a9d19",
            sourceFingerprint: 1375760032,
            note: .ledgerLegacy
        )
        
        let sut = URRegistry.shared
        
        let result = sut.getSourceHDKey(from: ur)
        
        XCTAssertEqual(result, expectedResult)
    }

    func testGetHDKeysWithLedgerLiveNote() {
        let ur1 = "UR:CRYPTO-ACCOUNT/1-3/LPADAXCFAXWNCYATPMKTJNHKADGYOEADCYGMAEJTNBAOLETAADDLONAOWKAXHDCLAOZEWTFTDNTEUEBYFHCASESNPAVANYOXTAECUOEEHDTLFWTSMTYKLFKNRKPAONLUHYAMTAADDYOTADLECSDWYKCSFNYKAEYKAEWKAEWKAOCYGMAEJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHTAADDLONAOWKAXHDCLAXFHCKUTWNTTRKDIIDZTZSIOZOSRHYBGUONLISSNDALTPMNBGOCLBALRYLLASEBENYAMTAADDYOTADLECSDWYKCSFNYKADYKAEWKAEWKAOCYGMAEJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHTAADDLONAOWKAXHDCLAOSKZTYLIYPMKTNBSAGHLSGTHGTOFMHSCXOERNHHDSJTNDPYVSNBFLTTONFNQDGWNNAMTAADDYOTADLECSDWYKCSFNYKAOYKAEWKAEWKAOCYGMAEJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHTAADDLONAOWKAXHDCLAOSNBDIELKYTFYSBOSVARNMSRSCTCHWTWDRLRHJKMEWZGD"
        let ur2 = "UR:CRYPTO-ACCOUNT/2-3/LPAOAXCFAXWNCYATPMKTJNHKADGYVAAETTLYSSCLQDRFVAVDYNTAFPWTAMTAADDYOTADLECSDWYKCSFNYKAXYKAEWKAEWKAOCYGMAEJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHTAADDLONAOWKAXHDCLAXGYYLCLAAVDEMWLGSKESWJTEODYKEJYTLRKWNMOCMLAADHGPMEEWMZECNDLCNSTGYAMTAADDYOTADLECSDWYKCSFNYKAAYKAEWKAEWKAOCYGMAEJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHTAADDLONAOWKAXHDCLAOAXLBLKHESEATGLIHGWWNCMCFPDRSDEUOSRUYHLAXJSMEWTMNREJPCPGMPEHGOXOLAMTAADDYOTADLECSDWYKCSFNYKAHYKAEWKAEWKAOCYGMAEJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHTAADDLONAOWKAXHDCLAXOXFPLDHLZOWLSTQDRSMNRDBNVEHSFGHTBBECBTMHDPWNIANBQDWTJTGWFDFXVWGWAMTAADDYOTADLECSDWYKCSFNYKAMYKAEWKAEWKAOCYGMAECXMTZCVA"
        let ur3 = "UR:CRYPTO-ACCOUNT/3-3/LPAXAXCFAXWNCYATPMKTJNHKADGYJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHTAADDLONAOWKAXHDCLAOPDUOURFDATEOONRLZOEOCEMWIERLVTWEYKCXJNLPLYZEFMDSRSTBUEETSPAMFSGSAMTAADDYOTADLECSDWYKCSFNYKATYKAEWKAEWKAOCYGMAEJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHTAADDLONAOWKAXHDCLAXKNCYIMFDPFNTGLFTADCPFREMSOTTCLDPLGOEATFGDYCXASMDHSISVYWDFRTEVTSPAMTAADDYOTADLECSDWYKCSFNYKAYYKAEWKAEWKAOCYGMAEJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHTAADDLONAOWKAXHDCLAXSWWTGELYFHCNKKNLFZRPZSFYSWSGFDPYVTGTWLZOROBWFRJKFWUYPYSOHPBAOXLYAMTAADDYOTADLECSDWYKCSFNYKASYKAEWKAEWKAOCYGMAEJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHAEAERDJZCHGL"
        let expectedResult = [
            CryptoHDKey(key: "02fef03a2bd3de113f1dc1cdb1e69aa4d935dc3458d542d796f5827abbb1a58b5e", chainCode: nil, sourceFingerprint: 1375760032, note: .ledgerLive),
            CryptoHDKey(key: "033f1eddf1d1bb2762fcfa67fbc35e12dc9968cd2587ada055210e84f780c1109a", chainCode: nil, sourceFingerprint: 1375760032, note: .ledgerLive),
            CryptoHDKey(key: "02c5fcf766ad77a0c254834d57ce3e6120a2be5c266e9babe8a047d1a53cb34f9e", chainCode: nil, sourceFingerprint: 1375760032, note: .ledgerLive),
            CryptoHDKey(key: "02cd0b648cf944cba7e6be97bf1f17f0eab7b9e600d181c421b3bce6e7f6d941f0", chainCode: nil, sourceFingerprint: 1375760032, note: .ledgerLive),
            CryptoHDKey(key: "0351f72104e737e94c7cc66e33307c74d5bbf19216800157ad34ebfe232f23c751", chainCode: nil, sourceFingerprint: 1375760032, note: .ledgerLive),
            CryptoHDKey(key: "02037f8c5fc1074e654ff11619a8bf28dcc3db5d037191f08eb5722252af57a4a6", chainCode: nil, sourceFingerprint: 1375760032, note: .ledgerLive),
            CryptoHDKey(key: "03a441895dfbe9c7b3bf8eba0ce461465a14350d902df163a0b3f06e4f4843e54f", chainCode: nil, sourceFingerprint: 1375760032, note: .ledgerLive),
            CryptoHDKey(key: "02a8dcdf480733a5b7fb331c9464b7e0edf5206d8581fe3e26bfd6de38c8063d4c", chainCode: nil, sourceFingerprint: 1375760032, note: .ledgerLive),
            CryptoHDKey(key: "037a1a6a48b09d4e3a01223b37c9d1212d8da20746302009956168e1ea3bd3e0c8", chainCode: nil, sourceFingerprint: 1375760032, note: .ledgerLive),
            CryptoHDKey(key: "03c6f04a813f23799940b6fa44c6ca48abe04de9fbb8133b7342dbabc95b0ea481", chainCode: nil, sourceFingerprint: 1375760032, note: .ledgerLive)
        ]
        
        let sut = URRegistry.shared
        
        let result1 = sut.getHDKeys(from: ur1)
        XCTAssertNil(result1)
        
        let result2 = sut.getHDKeys(from: ur2)
        XCTAssertNil(result2)
        
        let result3 = sut.getHDKeys(from: ur3)
        XCTAssertEqual(result3, expectedResult)
    }
    
    func testResetDecoder() {
        let ur1 = "UR:CRYPTO-ACCOUNT/1-3/LPADAXCFAXWNCYATPMKTJNHKADGYOEADCYGMAEJTNBAOLETAADDLONAOWKAXHDCLAOZEWTFTDNTEUEBYFHCASESNPAVANYOXTAECUOEEHDTLFWTSMTYKLFKNRKPAONLUHYAMTAADDYOTADLECSDWYKCSFNYKAEYKAEWKAEWKAOCYGMAEJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHTAADDLONAOWKAXHDCLAXFHCKUTWNTTRKDIIDZTZSIOZOSRHYBGUONLISSNDALTPMNBGOCLBALRYLLASEBENYAMTAADDYOTADLECSDWYKCSFNYKADYKAEWKAEWKAOCYGMAEJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHTAADDLONAOWKAXHDCLAOSKZTYLIYPMKTNBSAGHLSGTHGTOFMHSCXOERNHHDSJTNDPYVSNBFLTTONFNQDGWNNAMTAADDYOTADLECSDWYKCSFNYKAOYKAEWKAEWKAOCYGMAEJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHTAADDLONAOWKAXHDCLAOSNBDIELKYTFYSBOSVARNMSRSCTCHWTWDRLRHJKMEWZGD"
        let ur2 = "UR:CRYPTO-ACCOUNT/2-3/LPAOAXCFAXWNCYATPMKTJNHKADGYVAAETTLYSSCLQDRFVAVDYNTAFPWTAMTAADDYOTADLECSDWYKCSFNYKAXYKAEWKAEWKAOCYGMAEJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHTAADDLONAOWKAXHDCLAXGYYLCLAAVDEMWLGSKESWJTEODYKEJYTLRKWNMOCMLAADHGPMEEWMZECNDLCNSTGYAMTAADDYOTADLECSDWYKCSFNYKAAYKAEWKAEWKAOCYGMAEJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHTAADDLONAOWKAXHDCLAOAXLBLKHESEATGLIHGWWNCMCFPDRSDEUOSRUYHLAXJSMEWTMNREJPCPGMPEHGOXOLAMTAADDYOTADLECSDWYKCSFNYKAHYKAEWKAEWKAOCYGMAEJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHTAADDLONAOWKAXHDCLAXOXFPLDHLZOWLSTQDRSMNRDBNVEHSFGHTBBECBTMHDPWNIANBQDWTJTGWFDFXVWGWAMTAADDYOTADLECSDWYKCSFNYKAMYKAEWKAEWKAOCYGMAECXMTZCVA"
        let ur3 = "UR:CRYPTO-ACCOUNT/3-3/LPAXAXCFAXWNCYATPMKTJNHKADGYJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHTAADDLONAOWKAXHDCLAOPDUOURFDATEOONRLZOEOCEMWIERLVTWEYKCXJNLPLYZEFMDSRSTBUEETSPAMFSGSAMTAADDYOTADLECSDWYKCSFNYKATYKAEWKAEWKAOCYGMAEJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHTAADDLONAOWKAXHDCLAXKNCYIMFDPFNTGLFTADCPFREMSOTTCLDPLGOEATFGDYCXASMDHSISVYWDFRTEVTSPAMTAADDYOTADLECSDWYKCSFNYKAYYKAEWKAEWKAOCYGMAEJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHTAADDLONAOWKAXHDCLAXSWWTGELYFHCNKKNLFZRPZSFYSWSGFDPYVTGTWLZOROBWFRJKFWUYPYSOHPBAOXLYAMTAADDYOTADLECSDWYKCSFNYKASYKAEWKAEWKAOCYGMAEJTNBAXAHASISGRIHKKJKJYJLJTIHBKJKHSIAIAJLKPJTJYDMJZIHIEIOIHJPHEJZINKOIHAEAERDJZCHGL"
        
        let sut = URRegistry.shared
        
        sut.resetDecoder()
        
        let result1 = sut.getHDKeys(from: ur1)
        XCTAssertNil(result1)
        
        let result2 = sut.getHDKeys(from: ur2)
        XCTAssertNil(result2)
        
        let result3 = sut.getHDKeys(from: ur3)
        XCTAssertNotNil(result3)
        
        let result4 = sut.getHDKeys(from: ur1)
        XCTAssertNotNil(result4)
        
        sut.resetDecoder()
        
        let result5 = sut.getHDKeys(from: ur1)
        XCTAssertNil(result5)
        
        sut.resetDecoder()
    }
    
    func testGetUncompressedKeyFromEvenY() {
        let compressedKey = "02fef03a2bd3de113f1dc1cdb1e69aa4d935dc3458d542d796f5827abbb1a58b5e"
        let expectedResult = "04fef03a2bd3de113f1dc1cdb1e69aa4d935dc3458d542d796f5827abbb1a58b5ebdffecfa6587da3216d50114700e5e314650cc2268e9fcb6ac31593bcc71d178"
        
        let sut = URRegistry.shared
        
        let result = sut.getUncompressedKey(from: compressedKey)
        
        XCTAssertEqual(result, expectedResult)
    }
    
    func testGetUncompressedKeyFromOddY() {
        let compressedKey = "03b7db1c60fed9f333a5afb0f945c4fafc7739775bc4bda24ac6979362eca0f1f2"
        let expectedResult = "04b7db1c60fed9f333a5afb0f945c4fafc7739775bc4bda24ac6979362eca0f1f2ae4a073a1eb2f8bad6ddb7bcee0c475456d0c490eec0913c7bc30826fff3193d"
        
        let sut = URRegistry.shared
        
        let result = sut.getUncompressedKey(from: compressedKey)
        
        XCTAssertEqual(result, expectedResult)
    }
    
    func testNextPartUnsignedUR() {
        let signRequest = KeystoneSignRequest(
            requestId: "44313244443830392d443131312d344239352d384439372d324244423137324632363332",
            signData: "",
            signType: .typedTransaction,
            chainId: 4,
            path: "m/44'/60'/0'/0/0",
            xfp: 1375760032,
            address: "307832636539633861393136303233623031633737306535356439393165446642313734663035384335",
            origin: "gnosis safe ios"
        )
        let expectedResult1 = "UR:ETH-SIGN-REQUEST/1-1/LPADADCSLTCYGEJNWLGSHDLTOSADTPDAHDDKFYEHEYFYFYETDYESDPFYEHEHEHDPEEFWESECDPETFYESEMDPEYFWFYFWEHEMEYFGEYENEOEYAOFZAXAAAAAAAHTAADDYOEADLECSDWYKCSFNYKAEYKAEWKAEWKAOCYGMAEJTNBAMHDDRDYKSEYIAIHESIAETHSESEHENDYEYEOIDDYEHIAEMEMDYIHECECIEESESEHIHFYIYFWEHEMEEIYDYECETFXECATJLIOJTJLJKINJKCXJKHSIYIHCXINJLJKSAHPWTMK"
        let expectedResult2 = "UR:ETH-SIGN-REQUEST/2-1/LPAOADCSLTCYGEJNWLGSHDLTOSADTPDAHDDKFYEHEYFYFYETDYESDPFYEHEHEHDPEEFWESECDPETFYESEMDPEYFWFYFWEHEMEYFGEYENEOEYAOFZAXAAAAAAAHTAADDYOEADLECSDWYKCSFNYKAEYKAEWKAEWKAOCYGMAEJTNBAMHDDRDYKSEYIAIHESIAETHSESEHENDYEYEOIDDYEHIAEMEMDYIHECECIEESESEHIHFYIYFWEHEMEEIYDYECETFXECATJLIOJTJLJKINJKCXJKHSIYIHCXINJLJKIORHMTZE"
        
        let sut = URRegistry.shared
        sut.setSignRequestUREncoder(with: signRequest)
        
        let result1 = sut.nextPartUnsignedUR
        XCTAssertEqual(result1, expectedResult1)
        
        let result2 = sut.nextPartUnsignedUR
        XCTAssertEqual(result2, expectedResult2)
    }
    
    func testGetSignature() {
        let ur = "UR:ETH-SIGNATURE/OEADTPDAGDEEEODYFPEHETENESDPECFEECEHDPEEFYAOHDFPVLTNFGFHTKSPMSTOHHIHEEIHGSNLPEPLFLPMHKSOWZLSPFVOMEDWZCGTLTWTJYGTKIMYWKHLESMTGHHHZORPZEFERHURBSHDRLLUCWSOLYHTSODYGUAYCSSPBGBKGMUTCWZOQZRDGT"
        let expectedResult = KeystoneSignature(
            requestId: "34333041313836392d354535312d3444",
            signature: "e3da463fcfc897ce5c6534654c99afae47ad59c9f283b0e2912cfd4d87f0744d7d8ff45d3996545cfbb6fe45b9df0f58b78b1bc9815ac930530818c8120a52dd1b"
        )
        
        let sut = URRegistry.shared
        
        let result = sut.getSignature(from: ur)
        
        XCTAssertEqual(result, expectedResult)
    }
}
